/********************************************************************************
*                 Copyright (C) 2011 - Las Venturas Playground                  *
*                      http://sa-mp.nl | http://lvp-iv.com                      *
*                                                                               *
*    This program is free software: you can redistribute it and/or modify       *
*    it under the terms of the GNU General Public License as published by       *
*    the Free Software Foundation, either version 3 of the License, or          *
*    (at your option) any later version.                                        *
*                                                                               *
*    This program is distributed in the hope that it will be useful,            *
*    but WITHOUT ANY WARRANTY; without even the implied warranty of             *
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
*    GNU General Public License for more details.                               *
*                                                                               *
*    You should have received a copy of the GNU General Public License          *
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.      *
*                                                                               *
*********************************************************************************
*                                                                               *
*  Las Venturas Playground - Core/Account/functions.nut                         *
*                                                                               *
*  This file holds all database related functions.                              *
*  @author Matthias <matthias@sa-mp.nl>                                         *
*                                                                               *
********************************************************************************/

/**
 * This function registers a player.
 * @author: Matthias <matthias@sa-mp.nl>
 *
 * @param playerid The player to register
 * @param Password The password to register the player with
 * @param Email The email to register the player with.
 */
function RegisterPlayer (playerid, Password, Email)
{
    local Query = "";
    local Database = MySQL ();
    
    // Create the random salt
    local RandomSalt = RandomSalt ();
    // Hash the password together with the salt and a hardcoded salt.
    local HashedPassword = sha1 ("dg%$#^32d" + Password + RandomSalt);

    // Check if we still are connected.
    Database.checkConnection ();
    
    // Escape the hashed password, just to be sure.
    HashedPassword = Database.escapeString (HashedPassword);
    Email = Database.escapeString (Email);
    
    // We get the time.
    local dateTime = date (time ());
    local Time = format ("%d-%d-%d %02d:%02d:%02d", dateTime.year, (dateTime.month + 1), dateTime.day, dateTime.hour, dateTime.min, dateTime.sec );

    // Prepare and execute the queries.
    Query = "INSERT INTO profiles  ( nickname, user_password, password_salt, valid ) VALUES ( '" + getPlayerName (playerid) + "', '" + HashedPassword + "', '" + RandomSalt + "', 1 )";
    Database.query (Query);
    
    // Get the newly created profile ID from the profiles table.
    local ProfileID = Database.last_inserted();
    
    Query = "INSERT INTO profile_admin  ( profile_id, user_level ) VALUES ( '" + ProfileID.tostring() + "', '0' )";
    Database.query (Query);
    
    Query = "INSERT INTO profile_info  ( profile_id, reg_date, email, lastseen ) VALUES ( '" + ProfileID.tostring() + "', '" + Time + "', '" + Email + "', '" + Time + "' )";
    Database.query (Query);
    
    Query = "INSERT INTO profile_settings ( profile_id, skin ) VALUES ( '" + ProfileID.tostring() + "', '-1' )";
    Database.query (Query);
    
    Query = "INSERT INTO profile_stats ( profile_id, online_time, kills, deaths ) VALUES ( '" + ProfileID.tostring() + "', '0 0 0', '0', '0' )";
    Database.query (Query);
    
    Query = "INSERT INTO profile_stats_money ( profile_id, bank ) VALUES ( '" + ProfileID.tostring() + "', '0' )";
    Database.query (Query);
}

/**
 * This function logs a player in.
 * @author Matthias <matthias@sa-mp.nl>
 *
 * @param playerid The player to login
 * @param Password The password that the player entered.
 * @return true if the password was correct, false if the password is incorrect.
 */
function LogPlayerIn (playerid, Password)
{
    // Create a new instance of the MySQL class.
    local Database = MySQL ();
    
    // Check if we still are connected.
    Database.checkConnection ();

    // Todo: use profile id here.
    // We check if the player is registered.
    local EscapedName = Database.escapeString (getPlayerName (playerid));
    local Query = "SELECT password_salt, user_password FROM profiles WHERE nickname = '" + EscapedName + "'";
    local Result = Database.query (Query);
    local Rows = Database.fetch_assoc (Result);
    
    // Get the random salt and the password from the database
    local RandomSalt = Rows["password_salt"];
    local DatabasePassword = Rows["user_password"];
        
    // Regenerate the password.
    local TypedPassword = sha1 ("dg%$#^32d" + Password + RandomSalt);
        
    // Check if it's the same.
    if (TypedPassword == DatabasePassword)
    {
        // It is, return true!
        return true;
    }
    return false;
}

addEvent("LogPlayerIn", LogPlayerIn);

/**
 * This function resets all player variables
 * @author: Matthias <matthias@sa-mp.nl>
 *
 */
function ResetPlayerVariables( playerid )
{
    playerVehicle[playerid] = -1;
}

/**
 * This function generates a random salt
 * @author: Pugwipe <pugwipe@gmail.com>
 *
 * @return result The generated string.
 */
function RandomSalt () 
{
    local result = "";
    local len = random (6, 10);
    for (local i = 0; i < len; i++) 
    {
        local chr = random (33, 126);
        result += chr.tochar ();
    }
    
    return result;
}

/**
 * This function checks if a certain player is registered or not.
 * @author: Matthias <matthias@sa-mp.nl>
 *
 * @param playerid The player to check.
 */
function CheckUserStatus (playerid)
{
    isLoggedIn[playerid] = false;
    isRegistered[playerid] = false;
    
    playerInfo[playerid] <- 
    {
        ProfileID = -1
        Skin = -1
        Kills = 0
        Deaths = 0
        Level = 0
        Bank = 0
        OnlineTime = 0
    };
    
    // Create a new instance of the MySQL class.
    local Database = MySQL ();
    
    // Check if we still are connected.
    Database.checkConnection ();
    
    // Fetch the profile ID from the database, we check if he's registered.    
    local sEscapedName = Database.escapeString (getPlayerName (playerid));
    local Query = "SELECT profile_id FROM profiles WHERE nickname = '" + sEscapedName + "'";
    local Result = Database.query (Query);
    local Rows = Database.fetch_assoc (Result);
    
    // We need to make sure the user exists.
    if ("profile_id" in Rows ) 
    {
        isRegistered[playerid] = true;
    }
}

/**
 * This function loads the user data, in onPlayerConnect
 * @author: Matthias <matthias@sa-mp.nl>
 *
 * @param playerid The player to load the data from.
 */
function LoadUserData (playerid)
{  
    // Create a new instance of the MySQL class.
    local Database = MySQL ();
    
    // Check if we still are connected.
    Database.checkConnection ();
    
    // Fetch the profile ID from the database, we check if he's registered.    
    local Query = "SELECT profile_id FROM profiles WHERE nickname = '" + getPlayerName (playerid) + "'";
    local Result = Database.query (Query);
    local Rows = Database.fetch_assoc (Result);
    
    local DataQuery = @"
        SELECT
                kills, deaths, user_level, skin, bank, online_time
        FROM
                profiles
        LEFT JOIN
                profile_admin ON profile_admin.profile_id = profiles.profile_id
        LEFT JOIN
                profile_settings ON profile_settings.profile_id = profiles.profile_id
        LEFT JOIN
                profile_stats ON profile_stats.profile_id = profiles.profile_id
        LEFT JOIN
               profile_stats_money ON profile_stats_money.profile_id = profiles.profile_id
        WHERE
                profiles.profile_id = '" + Rows["profile_id"] + @"'
        LIMIT 1
    ";
       
    local DataResult = Database.query (DataQuery);
    local DataRows = Database.fetch_assoc (DataResult);
     
    // The profile ID exists, set it in the playerInfo array.
    playerInfo[playerid].ProfileID = Rows["profile_id"].tointeger();
    playerInfo[playerid].Skin = DataRows["skin"].tointeger();
    playerInfo[playerid].Kills = DataRows["kills"].tointeger();
    playerInfo[playerid].Deaths = DataRows["deaths"].tointeger();
    playerInfo[playerid].Level = DataRows["user_level"].tointeger();
    playerInfo[playerid].Bank = DataRows["bank"].tointeger();
    playerInfo[playerid].OnlineTime = DataRows["online_time"].tointeger();
    
    // Get the current server CPU tick count.
    onlineTime[playerid] = getTickCount ();
        
    // Load his skin if it's not -1 in the database.
    if (playerInfo[playerid].Skin != -1)
    {
        setPlayerModel (playerid, playerInfo[playerid].Skin);
    }
}

/**
 * This function saves the user data, in onPlayerDisconnect
 * @author: Matthias <matthias@sa-mp.nl>
 *
 * @param playerid The playerid that needs his data saved.
 */
function SaveUserData (playerid)
{  
    // Make sure he's logged in.
    if(isLoggedIn[playerid] == true)
    {
        // Create a new instance of the MySQL class.
        local Database = MySQL ();
        
        // Check if we still are connected.
        Database.checkConnection ();
        
        // We get the entire online time (saved in the database + current online time).
        local totalTime = playerInfo[playerid].OnlineTime + ((getTickCount () - onlineTime[playerid]) / 1000 );
        // We get the last seen time.
        local dateTime = date (time ());
        local Time = format ("%d-%d-%d %02d:%02d:%02d", dateTime.year, (dateTime.month + 1), dateTime.day, dateTime.hour, dateTime.min, dateTime.sec );
        
        // Update the profile_info table.
        Database.query ("UPDATE profile_info SET lastseen = '" + Time + "' WHERE profile_id = '" + playerInfo[playerid].ProfileID + "'");
        // profile_stats: kills, deaths, online_time
        Database.query ("UPDATE profile_stats SET kills = '" + playerInfo[playerid].Kills  + "', deaths = '" + playerInfo[playerid].Deaths  + "', online_time = '" + totalTime + "' WHERE profile_id = '" + playerInfo[playerid].ProfileID + "'");
    }
}